package service

import (
	"fmt"
	"reflect"
	"strings"
	"sync"
	appConfig "yunj/config"
	"yunj/pkg/global"
	"yunj/pkg/yunj/app/model"
	"yunj/pkg/yunj/config"
	"yunj/pkg/yunj/core/consts"
	"yunj/pkg/yunj/core/dto"
	"yunj/pkg/yunj/util"
)

type setting struct {
	Service
}

var (
	Setting   *setting
	initMutex sync.Mutex
)

// 获取设置值
// @param group string	分组标识
// @param key string	设置标识
func SettingValue[T any](group string, key string, def T) T {
	if group == "" || key == "" {
		return def
	}
	groupMap, exists := global.Setting[group]
	if !exists {
		return def
	}
	val, exists := groupMap[key]
	if !exists {
		return def
	}

	// 进行类型断言
	if v, ok := val.(T); ok {
		// 此处对v是否为空值进行判断，如果为空值，则返回默认值
		if reflect.ValueOf(v).IsValid() && !reflect.ValueOf(v).IsZero() {
			return v
		}
	}
	return def
}

// 初始化全局setting值
func InitGlobalSetting() (err error) {
	initMutex.Lock()
	defer initMutex.Unlock()
	setting := map[string]map[string]any{}
	// 获取默认的设置值
	configSettingGroups, exists := appConfig.Setting["groups"]
	if exists {
		configSettingGroupSlice, ok := configSettingGroups.([]map[string]any)
		if ok {
			for _, group := range configSettingGroupSlice {
				groupKey, exists := group["key"]
				if !exists {
					continue
				}
				groupKeyStr, ok := groupKey.(string)
				if !ok || groupKeyStr == "" {
					continue
				}
				form, exists := group["form"]
				if !exists {
					continue
				}
				formMap, ok := form.(map[string]any)
				if !ok {
					continue
				}
				formFieldDefault, exists := formMap["field_default"]
				if !exists {
					continue
				}
				formFieldDefaultMap, ok := formFieldDefault.(map[string]any)
				if !ok {
					continue
				}
				setting[groupKeyStr] = formFieldDefaultMap
			}
		}
	}

	// 查询数据库所有设置值
	var settings []model.Setting
	err = global.MySQL.Model(&model.Setting{}).Select("`group`,`key`,`value`").Find(&settings).Error
	if err != nil {
		err = fmt.Errorf("查询数据库所有设置值异常！%v", err)
		return
	}
	for _, item := range settings {
		if _, exists := setting[item.Group]; exists {
			setting[item.Group][item.Key] = item.Value
		} else {
			setting[item.Group] = map[string]any{item.Key: item.Value}
		}
	}

	global.Setting = setting
	return
}

// 获取允许的图片格式规则
func GetAllowImageExtRules() (res map[string]dto.FileExtRule) {
	res = map[string]dto.FileExtRule{}
	configs := util.MapMerge(config.ImageExtRules, appConfig.ImageExtRules)
	if settingExt := SettingValue("sys", "upload_img_ext", ""); settingExt != "" {
		settingExts := strings.Split(settingExt, ",")
		for _, ext := range settingExts {
			if rule, exists := configs[ext]; exists {
				res[ext] = rule
			}
		}
	}
	if len(res) == 0 {
		res = configs
	}
	return
}

// 获取允许的上传图片大小（单位：MB）
func GetAllowUploadImageSize() int64 {
	size, _ := util.ToInt64(SettingValue("sys", "upload_img_size", ""))
	if size <= 0 {
		size = consts.UPLOAD_IMG_SIZE
	}
	return size
}

// 获取允许的文件格式规则
func GetAllowFileExtRules() (res map[string]dto.FileExtRule) {
	res = map[string]dto.FileExtRule{}
	configs := util.MapMerge(config.FileExtRules, appConfig.FileExtRules)
	if settingExt := SettingValue("sys", "upload_file_ext", ""); settingExt != "" {
		settingExts := strings.Split(settingExt, ",")
		for _, ext := range settingExts {
			if rule, exists := configs[ext]; exists {
				res[ext] = rule
			}
		}
	}
	if len(res) == 0 {
		res = configs
	}
	return
}

// 获取允许的上传文件大小（单位：MB）
func GetAllowUploadFileSize() int64 {
	size, _ := util.ToInt64(SettingValue("sys", "upload_file_size", ""))
	if size <= 0 {
		size = consts.UPLOAD_IMG_SIZE
	}
	return size
}

// 获取允许的所有格式规则
// 包含图片和文件
func GetAllowAllExtRules() (res map[string]dto.FileExtRule) {
	res = map[string]dto.FileExtRule{}
	configs := util.MapMerge(config.AllExtRules, appConfig.AllExtRules)
	settingExts := []string{}
	if settingImgExt := SettingValue("sys", "upload_img_ext", ""); settingImgExt != "" {
		settingExts = append(settingExts, strings.Split(settingImgExt, ",")...)
	}
	if settingFileExt := SettingValue("sys", "upload_file_ext", ""); settingFileExt != "" {
		settingExts = append(settingExts, strings.Split(settingFileExt, ",")...)
	}
	for _, ext := range settingExts {
		if rule, exists := configs[ext]; exists {
			res[ext] = rule
		}
	}
	if len(res) == 0 {
		res = configs
	}
	return
}
